#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
系统工具日志模块
用于记录系统级别的操作、事件和性能指标
"""

import logging
import time
import json
import functools
import traceback
import socket
import os
import sys
import psutil
import threading
from datetime import datetime

# 获取系统日志记录器
system_logger = logging.getLogger('system')


def log_system_startup():
    """
    记录系统启动信息
    在应用启动时调用
    """
    system_logger = logging.getLogger("system.startup")
    system_info = {
        "timestamp": datetime.now().isoformat(),
        "hostname": socket.gethostname(),
        "pid": os.getpid(),
        "python_version": sys.version,
        "platform": sys.platform,
        "cpu_count": psutil.cpu_count(),
        "memory_total": psutil.virtual_memory().total,
        "disk_usage": psutil.disk_usage('/').total
    }
    
    system_logger.info(f"System Startup: {json.dumps(system_info, ensure_ascii=False)}")
    
    return system_info


def log_system_shutdown():
    """
    记录系统关闭信息
    在应用关闭时调用
    """
    hostname = socket.gethostname()
    uptime = get_uptime()
    
    system_logger.info(f"System Shutdown: Host={hostname}, Uptime={uptime}")


def get_uptime():
    """
    获取系统运行时间
    """
    # 以秒为单位获取系统运行时间
    uptime_seconds = time.time() - psutil.boot_time()
    # 转换为更易读的格式
    days, remainder = divmod(uptime_seconds, 86400)
    hours, remainder = divmod(remainder, 3600)
    minutes, seconds = divmod(remainder, 60)
    
    if days > 0:
        return f"{int(days)}d {int(hours)}h {int(minutes)}m"
    elif hours > 0:
        return f"{int(hours)}h {int(minutes)}m {int(seconds)}s"
    elif minutes > 0:
        return f"{int(minutes)}m {int(seconds)}s"
    else:
        return f"{int(seconds)}s"


def log_system_metrics(interval=300):
    """
    定期记录系统性能指标
    
    参数:
        interval: 记录间隔时间（秒）
    """
    system_logger = logging.getLogger("system.metrics")
    
    # 获取系统资源使用情况
    metrics = {
        "timestamp": datetime.now().isoformat(),
        "hostname": socket.gethostname(),
        "uptime": get_uptime(),
        "cpu_percent": psutil.cpu_percent(interval=1),
        "memory_usage": {
            "total": psutil.virtual_memory().total,
            "available": psutil.virtual_memory().available,
            "percent": psutil.virtual_memory().percent
        },
        "disk_usage": {
            "total": psutil.disk_usage('/').total,
            "used": psutil.disk_usage('/').used,
            "percent": psutil.disk_usage('/').percent
        },
        "network": {
            "connections": len(psutil.net_connections())
        },
        "processes": {
            "total": len(psutil.pids()),
            "running": len([p for p in psutil.process_iter() if p.status() == 'running'])
        }
    }
    
    system_logger.info(f"System Metrics: {json.dumps(metrics, ensure_ascii=False)}")
    
    # 安排下一次记录
    timer = threading.Timer(interval, log_system_metrics, [interval])
    timer.daemon = True
    timer.start()


def start_metric_logging(interval=300):
    """
    启动定期系统指标记录
    
    参数:
        interval: 记录间隔时间（秒）
    """
    log_system_metrics(interval)
    system_logger.info(f"Started system metric logging with interval of {interval} seconds")


def log_database_operation(operation_type):
    """
    数据库操作日志装饰器
    
    参数:
        operation_type: 操作类型，如 'QUERY', 'INSERT', 'UPDATE', 'DELETE'
    
    用法:
        @log_database_operation('UPDATE')
        def update_database_records(records):
            ...
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            # 记录操作开始
            system_logger.debug(f"DB Operation Start: {operation_type} - Function: {func.__name__}")
            
            try:
                # 执行原函数
                result = func(*args, **kwargs)
                
                # 计算操作时间
                duration = time.time() - start_time
                
                # 记录操作完成
                affected_records = getattr(result, 'rowcount', 0) if hasattr(result, 'rowcount') else 'unknown'
                system_logger.info(f"DB Operation Complete: {operation_type} - Function: {func.__name__} - Records: {affected_records} - Time: {duration:.2f}s")
                
                return result
                
            except Exception as e:
                # 记录操作失败
                system_logger.error(f"DB Operation Failed: {operation_type} - Function: {func.__name__} - Error: {str(e)}")
                system_logger.error(traceback.format_exc())
                raise
                
        return wrapper
    return decorator


def log_scheduled_task(task_name):
    """
    计划任务日志装饰器
    
    参数:
        task_name: 任务名称
    
    用法:
        @log_scheduled_task('Daily Data Cleanup')
        def cleanup_old_data():
            ...
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            # 记录任务开始
            system_logger.info(f"Scheduled Task Start: {task_name}")
            
            try:
                # 执行原函数
                result = func(*args, **kwargs)
                
                # 计算任务时间
                duration = time.time() - start_time
                
                # 记录任务完成
                system_logger.info(f"Scheduled Task Complete: {task_name} in {duration:.2f}s")
                
                return result
                
            except Exception as e:
                # 记录任务失败
                system_logger.error(f"Scheduled Task Failed: {task_name} - Error: {str(e)}")
                system_logger.error(traceback.format_exc())
                raise
                
        return wrapper
    return decorator


def log_error(error, context=None):
    """
    记录系统错误
    
    Args:
        error: 错误对象或错误消息
        context: 错误上下文信息，字典格式
    """
    system_logger = logging.getLogger("system.errors")
    
    # 获取堆栈跟踪
    error_traceback = traceback.format_exc() if not isinstance(error, str) else None
    
    # 记录错误信息
    log_entry = {
        "timestamp": datetime.now().isoformat(),
        "hostname": socket.gethostname(),
        "pid": os.getpid(),
        "error": str(error),
        "error_type": error.__class__.__name__ if not isinstance(error, str) else "string",
        "context": context if context else {}
    }
    
    if error_traceback and error_traceback != "NoneType: None\n":
        system_logger.error(f"System Error: {json.dumps(log_entry, ensure_ascii=False)}\n{error_traceback}")
    else:
        system_logger.error(f"System Error: {json.dumps(log_entry, ensure_ascii=False)}")


def log_security_event(event_type, description, severity="INFO", user=None, source_ip=None):
    """
    记录安全事件
    
    Args:
        event_type: 事件类型
        description: 事件描述
        severity: 事件严重性 (CRITICAL, WARNING, INFO)
        user: 相关用户
        source_ip: 来源IP
    """
    logger = logging.getLogger("system.security")
    
    event_data = {
        "event_type": event_type,
        "description": description,
        "timestamp": datetime.now().isoformat(),
        "hostname": socket.gethostname(),
        "pid": os.getpid()
    }
    
    if user:
        event_data["user"] = user
    
    if source_ip:
        event_data["source_ip"] = source_ip
    
    log_message = f"Security Event [{event_type}]: {description}"
    
    if severity.upper() == "CRITICAL":
        logger.critical(log_message, extra={"data": json.dumps(event_data, ensure_ascii=False)})
    elif severity.upper() == "WARNING":
        logger.warning(log_message, extra={"data": json.dumps(event_data, ensure_ascii=False)})
    else:
        logger.info(log_message, extra={"data": json.dumps(event_data, ensure_ascii=False)})


def log_command_execution(command, exit_code=None, output=None, error=None, user=None):
    """
    记录系统命令执行情况
    
    Args:
        command: 执行的命令
        exit_code: 命令退出码
        output: 命令输出
        error: 命令错误输出
        user: 执行命令的用户
    """
    logger = logging.getLogger("system.commands")
    
    command_data = {
        "command": command,
        "timestamp": datetime.now().isoformat(),
        "hostname": socket.gethostname(),
        "pid": os.getpid()
    }
    
    if exit_code is not None:
        command_data["exit_code"] = exit_code
    
    if output:
        # 限制输出大小，避免日志过大
        command_data["output"] = output[:1000] + "..." if len(output) > 1000 else output
    
    if error:
        command_data["error"] = error[:1000] + "..." if len(error) > 1000 else error
    
    if user:
        command_data["user"] = user
    
    if exit_code == 0:
        logger.info(f"Command executed successfully: {command}", 
                    extra={"data": json.dumps(command_data, ensure_ascii=False)})
    else:
        logger.warning(f"Command execution failed with code {exit_code}: {command}", 
                       extra={"data": json.dumps(command_data, ensure_ascii=False)}) 